package com.t.bricks.bussiness.controller.customer;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.t.bricks.bussiness.controller.common.BaseController;
import com.t.bricks.bussiness.db.entity.customer.Customer;
import com.t.bricks.bussiness.model.customer.AddEntity;
import com.t.bricks.bussiness.service.customer.CustomerService;
import com.t.bricks.model.MsgEmity;
import com.t.bricks.utils.modules.web.FindByPageParam;
import com.t.bricks.utils.spring.ModuleUtil;

/**
 * 顾客信息控制层
 * 继承BaseController可直接实现通用方法,三个泛型代表:业务类、实体类、查询类
 * 通用业务类CommonService已经包含常用功能,使用自定义CustomerService(需实现)可覆盖通用方法或扩展业务功能
 * 通用查询类可以直接使用Map,否则使用自定义ConditionCustomer(需实现)
 * @author HuangXinBian
 * @DateTime 2022年06月22日 15:25:25
 */
@RestController
@Api(value="顾客信息", tags={"顾客信息操作接口"})
@RequestMapping("/customer/")
public class CustomerController extends BaseController<CustomerService<Customer>, Customer, Map<String, Object>> {
	
	/**
	 * 控制操作,首位9不参与用6个数代表开关,0为不限制,1为限制
	 * 6个数的控制分别是:删除、修改、查询、导出、统计、步骤值可逆
	 * 其中前5个为'是否仅创建者可操作'后续为其它控制开关
	 */
	protected int enableTag = 9111110;

	/**
	 * 设置 检查待新增内容是否存在重复数据(多字段组合重复即重复)集合
	 * @return 返回的集合将覆盖父类的checkRepeatCombination成员,若返回null则不进行重复校验
	 */
	@Override
	protected List<String> setCheckRepeatCombination() {
		return null;//例:Arrays.asList("sName", "sCreator");
	}

	/**
	 * 设置 检查待新增内容是否存在重复数据(单独字段重复即重复)集合
	 * @return 返回的集合将覆盖父类的checkRepeatAlone成员,若返回null则不进行重复校验
	 */
	@Override
	protected Map<String, Integer> setCheckRepeatAlone() {
		Map<String, Integer> map = new HashMap<>(3);
		map.put("sName", 1);
		map.put("sAliases", 10);
		map.put("sNo", 100);
		
		return map;
	}
	
	/**
	 * 记录编号值前缀,此属性用于给id字段添加前缀,以便于在分布式系统中进行数据合并
	 * 注意:必须规划好各个模块的前缀,如果没有数据合并的需要则不需要设置,默认没有前缀
	 * 前缀只有1个字符
	 */
	protected String idValuePrefix = "F";//有登录要求,因此必须使用编号前缀,分配前缀:F

	/**
	 * 修改数据
	 * @param customer 顾客信息实体对象
	 * @return MsgEmity
	 */
	@ApiOperation(value="修改数据", response=Customer.class)
	@RequestMapping(method={RequestMethod.POST}, value="/edit")
	@Override
	public MsgEmity edit(@RequestBody Customer customer) {
		customer.setsOwner("BricksMall.Customer");//用户来源绝对不能由外界传入
		customer.setsPass(null);//密码不能在此修改
		customer.setsSignPass(null);//手势密码不能在此修改
		customer.setsName(null);//姓名不能在此修改
		customer.setsNo(null);//识别号(电话)不能在此修改
		customer.setsType(null);//用户类型不能在此修改
		
		return super.edit(customer);//直接使用父类中定义的方法,否则使用customerService.edit(customer);
	}

	/**
	 * 根据记录编号查询符合分页数据的某条记录
	 * @param id 记录编号
	 * @return MsgEmity
	 */
	@ApiOperation(value="根据记录编号查询符合分页数据的某条记录", response=Customer.class)
	@RequestMapping(method={RequestMethod.POST}, value="/find/page/row")
	@Override
	public MsgEmity findByPageRow(String id) {
		return super.findByPageRow(id);//直接使用父类中定义的方法,否则使用customerService.findByPageRow(id);
	}

	/**
	 * 查询分页数据
	 * @param findByPageParam 分页查询条件组合类
	 * 结构参考: {"page": 分页请求信息对象, "orders": 排序信息对象集合, "sLikeStr": 全文检索, "condition": 查询条件对象}
	 * @return MsgEmity 返回查询结果
	 */
	@ApiOperation(value="查询分页数据", response=Customer.class)
	@RequestMapping(method={RequestMethod.POST}, value="/find/page")
	@Override
	public MsgEmity findByPage(@RequestBody FindByPageParam<Map<String, Object>> findByPageParam) {//findByPage(@RequestBody FindByPageParam<ConditionCustomer> findByPageParam)
		return super.findByPage(findByPageParam);//直接使用父类中定义的方法,否则使用 customerService.findByPage(findByPageParam.getPage(), findByPageParam.getOrders(), findByPageParam.getsLikeStr(), findByPageParam.getCondition());
	}

	//---------------------------- 自动生成代码结束 ----------------------------//

	/**
	 * 新增顾客信息
	 * @param addEntity 新增顾客对象实体
	 * @return MsgEmity
	 */
	@ApiOperation(value="新增顾客信息", response=AddEntity.class)
	@RequestMapping(method={RequestMethod.POST}, value="/add")
	public MsgEmity add(@RequestBody AddEntity addEntity) {
		return this.service().addCustom(addEntity);
	}

	/**
	 * 删除数据
	 * @param id 记录编号
	 * @return MsgEmity
	 */
	@RequestMapping(method={RequestMethod.POST}, value="/del")
	@Override
	public MsgEmity del(String id) {
		return this.service().del(id);//直接使用父类中定义的方法,否则使用customerService.del(iVersion, uId);
	}

	/**
	 * 修改当前用户密码
	 * @param sOldPass
	 * @param sNewPass
	 * @return
	 */
	//[start]
	@ApiOperation(value="修改当前用户密码", notes="只有当前用户才能修改密码,且必须提供当前密码")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sOldPass", value="旧密码", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="sNewPass", value="新密码", dataType="String", paramType="query", required=true)
	})
	@ApiResponses({
		@ApiResponse(code=200, message="{\"success\": 布尔值, \"msg\": 文字提示, \"data\": 码值|Json数据对象集合}"),
		@ApiResponse(code=400, message="错误的请求,请检查路径"),
		@ApiResponse(code=404, message="请求路径没有或页面跳转路径不对"),
		@ApiResponse(code=1000001, message="内部请求密钥错误"),
		@ApiResponse(code=1000002, message="您还没有登录或登录已超时,需要重新登录"),
		@ApiResponse(code=1000003, message="检查登录状态失败,请稍后重试！"),
		@ApiResponse(code=1000004, message="请求的操作不存在,请检查访问地址正确性，如大小写"),
		@ApiResponse(code=1000005, message="响应后在系统内部发生不可预知的错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=8001, message="无法获取当前用户信息"),
		@ApiResponse(code=8002, message="旧密码参数为空"),
		@ApiResponse(code=8003, message="新密码参数为空"),
		@ApiResponse(code=8004, message="没有查找到当前用户"),
		@ApiResponse(code=8005, message="没有查找到对应用户信息"),
		@ApiResponse(code=8006, message="用户被限制"),
		@ApiResponse(code=8007, message="提供的旧密码错误"),
		@ApiResponse(code=8999, message="密码无需修改"),
		@ApiResponse(code=7001, message="预期的修改未成功"),
		@ApiResponse(code=7002, message="修改时发生异常"),
		@ApiResponse(code=7003, message="7003~7998为修改时发生的其它错误"),
		@ApiResponse(code=7999, message="密码修改成功")
	})
	//[end]
	@RequestMapping(method={RequestMethod.POST}, value="/password/edit")
	public MsgEmity editPass(String sOldPass, String sNewPass) {
		String currentLoginUserId = ModuleUtil.currentLoginUserId();//取当前登录用户
		return this.service().editPass(currentLoginUserId, sOldPass, sNewPass);
	}

	/**
	 * 重置密码
	 * @param uId 待重置密码的账号
	 * @param sPass 当前操作用户的密码
	 * @return
	 */
	//[start]
	@ApiOperation(value="重置密码", notes="只有当前用户和管理员(admin)才能重置密码")
	@ApiImplicitParams({
		@ApiImplicitParam(name="uId", value="表编号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="sPass", value="新密码", dataType="String", paramType="query", required=true)
	})
	@ApiResponses({
		@ApiResponse(code=200, message="{\"success\": 布尔值, \"msg\": 文字提示, \"data\": 码值|Json数据对象集合}"),
		@ApiResponse(code=400, message="错误的请求,请检查路径"),
		@ApiResponse(code=404, message="请求路径没有或页面跳转路径不对"),
		@ApiResponse(code=1000001, message="内部请求密钥错误"),
		@ApiResponse(code=1000002, message="您还没有登录或登录已超时,需要重新登录"),
		@ApiResponse(code=1000003, message="检查登录状态失败,请稍后重试！"),
		@ApiResponse(code=1000004, message="请求的操作不存在,请检查访问地址正确性，如大小写"),
		@ApiResponse(code=1000005, message="响应后在系统内部发生不可预知的错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=8001, message="用户编号为空"),
		@ApiResponse(code=8002, message="未能获取操作人员信息"),
		@ApiResponse(code=8003, message="仅允许管理员或该账号用户重置密码"),
		@ApiResponse(code=8004, message="当前操作用户信息错误"),
		@ApiResponse(code=8005, message="提供的操作用户密码错误"),
		@ApiResponse(code=8006, message="没有查找到待重置密码的用户"),
		@ApiResponse(code=8999, message="密码无需修改重置"),
		@ApiResponse(code=7001, message="预期的修改未成功"),
		@ApiResponse(code=7002, message="修改时发生异常"),
		@ApiResponse(code=7003, message="7003~7998为修改时发生的其它错误"),
		@ApiResponse(code=7999, message="密码修改成功")
	})
	//[end]
	@RequestMapping(method={RequestMethod.POST}, value="/password/reset")
	public MsgEmity resetPass(String uId, String sPass) {
		return this.service().resetPass(uId, sPass);//重置密码
	}
	
	/**
	 * 修改当前用户手势密码
	 * @param sOldPass
	 * @param sNewPass
	 * @return
	 */
	//[start]
	@ApiOperation(value="修改当前用户手势密码", notes="只有当前用户才能修改手势密码,且必须提供当前手势密码")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sOldPass", value="旧密码", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="sNewPass", value="新密码", dataType="String", paramType="query", required=true)
	})
	@ApiResponses({
		@ApiResponse(code=200, message="{\"success\": 布尔值, \"msg\": 文字提示, \"data\": 码值|Json数据对象集合}"),
		@ApiResponse(code=400, message="错误的请求,请检查路径"),
		@ApiResponse(code=404, message="请求路径没有或页面跳转路径不对"),
		@ApiResponse(code=1000001, message="内部请求密钥错误"),
		@ApiResponse(code=1000002, message="您还没有登录或登录已超时,需要重新登录"),
		@ApiResponse(code=1000003, message="检查登录状态失败,请稍后重试！"),
		@ApiResponse(code=1000004, message="请求的操作不存在,请检查访问地址正确性，如大小写"),
		@ApiResponse(code=1000005, message="响应后在系统内部发生不可预知的错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=8001, message="无法获取当前用户信息"),
		@ApiResponse(code=8002, message="旧密码参数为空"),
		@ApiResponse(code=8003, message="新密码参数为空"),
		@ApiResponse(code=8004, message="没有查找到当前用户"),
		@ApiResponse(code=8005, message="没有查找到对应用户信息"),
		@ApiResponse(code=8006, message="用户被限制"),
		@ApiResponse(code=8007, message="提供的旧密码错误"),
		@ApiResponse(code=8999, message="密码无需修改"),
		@ApiResponse(code=7001, message="预期的修改未成功"),
		@ApiResponse(code=7002, message="修改时发生异常"),
		@ApiResponse(code=7003, message="7003~7998为修改时发生的其它错误"),
		@ApiResponse(code=7999, message="密码修改成功")
	})
	//[end]
	@RequestMapping(method={RequestMethod.POST}, value="/password/edit/sign")
	public MsgEmity editSignPass(String sOldPass, String sNewPass) {
		String currentLoginUserId = ModuleUtil.currentLoginUserId();//取当前登录用户
		return this.service().editSignPass(currentLoginUserId, sOldPass, sNewPass);
	}

	/**
	 * 重置手势密码
	 * @param uId 待重置密码的账号
	 * @param sPass 当前操作用户的密码
	 * @return
	 */
	//[start]
	@ApiOperation(value="重置手势密码", notes="只有当前用户和管理员(admin)才能重置手势密码")
	@ApiImplicitParams({
		@ApiImplicitParam(name="uId", value="表编号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="sPass", value="新密码", dataType="String", paramType="query", required=true)
	})
	@ApiResponses({
		@ApiResponse(code=200, message="{\"success\": 布尔值, \"msg\": 文字提示, \"data\": 码值|Json数据对象集合}"),
		@ApiResponse(code=400, message="错误的请求,请检查路径"),
		@ApiResponse(code=404, message="请求路径没有或页面跳转路径不对"),
		@ApiResponse(code=1000001, message="内部请求密钥错误"),
		@ApiResponse(code=1000002, message="您还没有登录或登录已超时,需要重新登录"),
		@ApiResponse(code=1000003, message="检查登录状态失败,请稍后重试！"),
		@ApiResponse(code=1000004, message="请求的操作不存在,请检查访问地址正确性，如大小写"),
		@ApiResponse(code=1000005, message="响应后在系统内部发生不可预知的错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=8001, message="用户编号为空"),
		@ApiResponse(code=8002, message="未能获取操作人员信息"),
		@ApiResponse(code=8003, message="仅允许管理员或该账号用户重置密码"),
		@ApiResponse(code=8004, message="当前操作用户信息错误"),
		@ApiResponse(code=8005, message="提供的操作用户密码错误"),
		@ApiResponse(code=8006, message="没有查找到待重置密码的用户"),
		@ApiResponse(code=8999, message="密码无需修改重置"),
		@ApiResponse(code=7001, message="预期的修改未成功"),
		@ApiResponse(code=7002, message="修改时发生异常"),
		@ApiResponse(code=7003, message="7003~7998为修改时发生的其它错误"),
		@ApiResponse(code=7999, message="密码修改成功")
	})
	//[end]
	@RequestMapping(method={RequestMethod.POST}, value="/password/reset/sign")
	public MsgEmity resetSignPass(String uId, String sPass) {
		return this.service().resetSignPass(uId, sPass);//重置密码
	}

	/**
	 * 验证当前账号密码
	 * @param uId 账号
	 * @param sPass 待验证手势密码
	 * @return
	 */
	@ApiOperation(value="验证当前账号密码", notes="只能验证当前用户密码")
	@ApiImplicitParams({
		@ApiImplicitParam(name="uId", value="账号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="sPass", value="待验证手势密码", dataType="String", paramType="query", required=true)
	})
	@RequestMapping(method={RequestMethod.POST}, value="/password/check")
	public MsgEmity checkPass(String uId, String sPass) {
		return this.service().checkPass(uId, sPass);
	}

	/**
	 * 验证当前账号手势密码
	 * @param uId 账号
	 * @param sPass 待验证手势密码
	 * @return
	 */
	@ApiOperation(value="验证当前账号手势密码", notes="只能验证当前用户手势密码")
	@ApiImplicitParams({
		@ApiImplicitParam(name="uId", value="账号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="sPass", value="待验证手势密码", dataType="String", paramType="query", required=true)
	})
	@RequestMapping(method={RequestMethod.POST}, value="/password/check/sign")
	public MsgEmity checkSignPass(String uId, String sPass) {
		return this.service().checkSignPass(uId, sPass);
	}

	/**
	 * 请求发送手机验证码
	 * @param sPhone 手机号
	 * @return
	 */
	@ApiOperation(value="请求发送手机验证码", notes="向指定手机发送验证码")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sPhone", value="手机号", dataType="String", paramType="query", required=true)
	})
	@RequestMapping(method={RequestMethod.POST}, value="/send/identifying/code")
	public MsgEmity sendIdentifyingCode(String sPhone) {
		return this.service().sendIdentifyingCode(sPhone);
	}

	/**
	 * 忘记密码
	 * @param sNo 识别号(电话)
	 * @param iCode 短信验证码
	 * @param sNewPass 新密码
	 * @return
	 */
	@ApiOperation(value="忘记密码", notes="根据识别号设置新密码")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sNo", value="手机号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="iCode", value="短信验证码", dataType="Integer", paramType="query", required=true),
		@ApiImplicitParam(name="sNewPass", value="新密码", dataType="String", paramType="query", required=true)
	})
	@RequestMapping(method={RequestMethod.POST}, value="/forget/pass")
	public MsgEmity forgetPass(String sNo, Integer iCode, String sNewPass) {
		return this.service().forgetPass(sNo, iCode, sNewPass);
	}

	/**
	 * 根据手机号(sNo)与关注号进行登录
	 * @param sNo 识别号(电话)
	 * @param sOpenId 关注号
	 * @param iType 类型(1:微信)
	 * @param sOwner 用户来源表
	 * @param iDevice 设备类型,1:PC,2:手机,3:平板,4.....
	 * @return
	 */
	@ApiOperation(value="根据手机号(sNo)与关注号进行登录")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sNo", value="手机号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="sOpenId", value="关注号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="iType", value="(1:微信)", dataType="Integer", paramType="query", required=false),
		@ApiImplicitParam(name="sOwner", value="用户来源表", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="iDevice", value="设备类型,1:PC,2:手机,3:平板,4.....", dataType="Integer", paramType="query", required=false)
	})
	@RequestMapping(method={RequestMethod.POST}, value="/login")
	public MsgEmity login(String sNo, String sOpenId, Integer iType, String sOwner, Integer iDevice) {
		return this.service().login(sNo, sOpenId, iType, sOwner, iDevice);
	}

	/**
	 * 根据手机号(sNo)判断是否与关注号进行绑定
	 * @param sNo 识别号(电话)
	 * @param iType 类型(1:微信)
	 * @return
	 */
	@ApiOperation(value="根据手机号(sNo)判断是否与关注号进行绑定")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sNo", value="手机号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="iType", value="(1:微信)", dataType="Integer", paramType="query", required=false)
	})
	@RequestMapping(method={RequestMethod.POST}, value="/has/openid")
	public MsgEmity hasOpenId(String sNo, Integer iType) {
		return this.service().hasOpenId(sNo, iType);
	}

	/**
	 * 绑定关注号
	 * @param uId 记录编号
	 * @param sOpenId 关注号
	 * @param sPass 当前密码
	 * @param iType 类型(1:微信)
	 * @return
	 */
	@ApiOperation(value="绑定关注号", notes="提供的密码必须与当前密码一致")
	@ApiImplicitParams({
		@ApiImplicitParam(name="uId", value="记录编号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="sOpenId", value="关注号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="sPass", value="当前密码", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="iType", value="(1:微信)", dataType="Integer", paramType="query", required=false)
	})
	@RequestMapping(method={RequestMethod.POST}, value="/binding")
	public MsgEmity bindingOpenId(String uId, String sOpenId, String sPass, Integer iType) {
		return this.service().bindingOpenId(uId, sOpenId, sPass, iType);
	}

	/**
	 * 设置微信用户统一标识
	 * @param sWechatUid 微信用户统一标识
	 * @return
	 */
	@ApiOperation(value="设置微信用户统一标识", notes="设置当前用户微信用户统一标识")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sWechatUid", value="微信用户统一标识", dataType="String", paramType="query", required=true)
	})
	@RequestMapping(method={RequestMethod.POST}, value="/edit/wechatid")
	public MsgEmity setWechatid(String sWechatUid) {
		return this.service().setWechatid(sWechatUid);
	}
	
	/**
	 * 根据微信用户统一标识获取电话信息
	 * @param sWechatUid 微信用户统一标识
	 * @return
	 */
	@ApiOperation(value="获取电话信息", notes="根据微信用户统一标识获取电话信息")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sWechatUid", value="微信用户统一标识", dataType="String", paramType="query", required=true)
	})
	@RequestMapping(method={RequestMethod.POST}, value="/phone/wechatid")
	public MsgEmity getNoByWechatUid(String sWechatUid) {
		return this.service().getNoByWechatUid(sWechatUid);
	}
	
	/**
	 * 判断微信用户唯一标识是否已经绑定
	 * @param sWechatUid 微信用户统一标识
	 * @return 返回手机号
	 */
	@ApiOperation(value="判断微信用户唯一标识是否已经绑定", notes="判断微信用户唯一标识是否已经绑定")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sWechatUid", value="微信用户统一标识", dataType="String", paramType="query", required=true)
	})
	@RequestMapping(method={RequestMethod.POST}, value="/has/openid/wechatid")
	public MsgEmity hasWechatUid(String sWechatUid) {
		return this.service().hasWechatUid(sWechatUid);
	}

	/**
	 * 根据微信用户唯一标识进行登录
	 * @param sWechatUid 微信用户统一标识
	 * @param iDevice 设备类型,1:PC,2:手机,3:平板,4.....
	 * @return
	 */
	@ApiOperation(value="根据微信用户唯一标识进行登录", notes="根据微信用户唯一标识进行登录")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sWechatUid", value="微信用户统一标识", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="iDevice", value="设备类型,1:PC,2:手机,3:平板,4.....", dataType="Integer", paramType="query", required=false)
	})
	@RequestMapping(method={RequestMethod.POST}, value="/login/wechatid")
	public MsgEmity loginByWechatUid(String sWechatUid, Integer iDevice) {
		return this.service().loginByWechatUid(sWechatUid, iDevice);
	}

	/**
	 * 删除当前账户数据
	 * @return MsgEmity
	 */
	@ApiOperation(value="删除当前账户数据", notes="根据调用的token删除账户")
	@RequestMapping(method={RequestMethod.POST}, value="/del/current")
	public MsgEmity delCurrent() {
		String currentLoginUserId = ModuleUtil.currentLoginUserId();//取当前登录用户
		return this.service().del(currentLoginUserId);
	}
	
}
